package com.qingyun.shop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qingyun.common.annotation.Log;
import com.qingyun.common.constant.Constants;
import com.qingyun.common.core.domain.entity.SysRole;
import com.qingyun.common.core.domain.entity.SysUser;
import com.qingyun.common.core.domain.model.LoginUser;
import com.qingyun.common.core.mybatisplus.core.ServicePlusImpl;
import com.qingyun.common.core.page.TableDataInfo;
import com.qingyun.common.core.redis.RedisCache;
import com.qingyun.common.exception.CustomException;
import com.qingyun.common.utils.PageUtils;
import com.qingyun.common.utils.StringUtils;
import com.qingyun.security.model.shop.AppLoginUser;
import com.qingyun.security.utils.SecurityUtils;
import com.qingyun.shop.domain.*;
import com.qingyun.shop.domain.bo.apply.TiktokApplyProxyAddBo;
import com.qingyun.shop.domain.bo.apply.TiktokApplyProxyEditBo;
import com.qingyun.shop.domain.bo.apply.TiktokApplyProxyQueryBo;
import com.qingyun.shop.domain.vo.TiktokApplyProxyListVo;
import com.qingyun.shop.domain.vo.TiktokApplyProxyVo;
import com.qingyun.shop.mapper.TiktokApplyProxyMapper;
import com.qingyun.shop.mapper.TiktokShopMapper;
import com.qingyun.shop.mapper.TiktokUserProxyMapper;
import com.qingyun.shop.mapper.TiktokUserShopMapper;
import com.qingyun.shop.service.ITiktokApplyProxyService;
import com.qingyun.shop.service.ITiktokProxyBranchConfigService;
import com.qingyun.shop.service.ITiktokProxyService;
import com.qingyun.system.domain.SysUserRole;
import com.qingyun.system.mapper.SysUserMapper;
import com.qingyun.system.mapper.SysUserRoleMapper;
import com.qingyun.system.service.ISysRoleService;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 代理商申请Service业务层处理
 *
 * @author qingyun
 * @date 2021-09-10
 */
@Service
@AllArgsConstructor
public class TiktokApplyProxyServiceImpl extends ServicePlusImpl<TiktokApplyProxyMapper, TiktokApplyProxy, TiktokApplyProxyVo> implements ITiktokApplyProxyService {

	private final TiktokShopMapper shopMapper;


	private final SysUserMapper userMapper;

	private final TiktokUserProxyMapper userProxyMapper;

	private final ITiktokProxyService proxyService;

	private final ISysRoleService  roleService;

	private final SysUserRoleMapper userRoleMapper;

	private final ITiktokProxyBranchConfigService tiktokProxyBranchConfigService;

	private final MapperFacade mapperFacade;

	private final RedisCache redisCache;

	@Override
	public TiktokApplyProxyVo queryById(Long id) {
		TiktokApplyProxyVo voById = getVoById(id);
		TiktokShop tiktokShop = shopMapper.selectOne(Wrappers.lambdaQuery(TiktokShop.class).select(TiktokShop::getName).eq(TiktokShop::getId, voById.getShopId()));
		voById.setShopName(tiktokShop.getName());
		return voById;
	}

	@Override
	public TableDataInfo<TiktokApplyProxyListVo> queryPageList(TiktokApplyProxyQueryBo bo) {
		Page<TiktokApplyProxyListVo> result = baseMapper.selectApplyProxyList(PageUtils.buildPage(), bo);
		return PageUtils.buildDataInfo(result);
	}

	@Override
	public List<TiktokApplyProxyVo> queryList(TiktokApplyProxyQueryBo bo) {
		return listVo(buildQueryWrapper(bo));
	}

	private LambdaQueryWrapper<TiktokApplyProxy> buildQueryWrapper(TiktokApplyProxyQueryBo bo) {
		LambdaQueryWrapper<TiktokApplyProxy> lqw = Wrappers.lambdaQuery();
		lqw.eq(bo.getShopId() != null, TiktokApplyProxy::getShopId, bo.getShopId());
		lqw.eq(bo.getUserId() != null, TiktokApplyProxy::getUserId, bo.getUserId());
		lqw.like(StringUtils.isNotBlank(bo.getRealName()), TiktokApplyProxy::getRealName, bo.getRealName());
		lqw.eq(StringUtils.isNotBlank(bo.getUserPhone()), TiktokApplyProxy::getUserPhone, bo.getUserPhone());
		lqw.between(bo.getApplyTimeStart() != null && bo.getApplyTimeEnd() != null, TiktokApplyProxy::getApplyTime, bo.getApplyTimeStart(), bo.getApplyTimeEnd());
		lqw.eq(bo.getStatus() != null, TiktokApplyProxy::getStatus, bo.getStatus());
		return lqw;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean insertByBo(TiktokApplyProxyAddBo bo) {
		TiktokApplyProxy applyProxy = mapperFacade.map(bo, TiktokApplyProxy.class);
		validEntityBeforeSave(applyProxy);

		Long userId = SecurityUtils.getUser().getUserId();
		Long shopId = SecurityUtils.getShop().getId();

		applyProxy.setApplyTime(new Date());
		applyProxy.setShopId(shopId);
		applyProxy.setUserId(userId);

		return save(applyProxy);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean updateByBo(TiktokApplyProxyEditBo bo) {
		TiktokApplyProxy update = BeanUtil.toBean(bo, TiktokApplyProxy.class);
		validEntityBeforeSave(update);
		return updateById(update);
	}

	/**
	 * 保存前的数据校验
	 *
	 * @param entity 实体类数据
	 */
	private void validEntityBeforeSave(TiktokApplyProxy entity) {
		//TODO 做一些数据校验,如唯一约束
	}

	@Override
	public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
		if (isValid) {
			//TODO 做一些业务上的校验,判断是否需要校验
		}
		return removeByIds(ids);
	}

	/**
	 * 校验是否已申请，是否已是代理身份
	 */
	@Override
	public void checkShopIsProxy(Long shopId) {

		TiktokShop tiktokShop = shopMapper.selectById(shopId);
		if (ObjectUtil.isNull(tiktokShop)) {
			throw new CustomException("商户不存在");
		}

		if (tiktokShop.getIsProxy().equals(1)) {
			throw new CustomException("您已经是代理商商户了，请勿重复申请");
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean checkShopApplyProxy(TiktokApplyProxy apply,Integer status,String context){
        //修改状态 修改用户角色 修改用户类型  添加代理商记录 添加用户和代理商关联记录
		apply.setStatus(status);
		apply.setPassTime(new Date());
		apply.setReject(context);
		updateById(apply);
		//审核通过
		if (status.equals(1)) {
			Long userId = apply.getUserId();
			SysUser user = userMapper.selectUserById(userId);
			user.setUserType(Constants.PROXY_USER);
			userMapper.updateById(user);

			SysRole roleKey = roleService.lambdaQuery().eq(SysRole::getRoleKey, "proxy_role_key").one();
			SysUserRole sysUserRole = new SysUserRole();
			sysUserRole.setRoleId(roleKey.getRoleId());
			userRoleMapper.update(sysUserRole,Wrappers.lambdaQuery(SysUserRole.class).eq(SysUserRole::getUserId,userId));

			TiktokShop shop = shopMapper.selectById(apply.getShopId());

			TiktokProxy tiktokProxy = mapperFacade.map(shop, TiktokProxy.class);
			tiktokProxy.setId(null);
			tiktokProxy.setVideoCount(0L);
			tiktokProxy.setAncestors("0");
			tiktokProxy.setParentId(1L);
			tiktokProxy.setShopId(shop.getId());
			proxyService.save(tiktokProxy);

			//默认配置
			TiktokProxyBranchConfig config=new TiktokProxyBranchConfig();
			config.setProxyId(tiktokProxy.getId());
			config.setProxyPrice(new BigDecimal(1));
			config.setOneProxyRatio(new BigDecimal(0.2));
			config.setTowProxyRatio(new BigDecimal(0.3));
			tiktokProxyBranchConfigService.save(config);


			shop.setIsProxy(1);
			shop.setProxyId(tiktokProxy.getId());
			shopMapper.updateById(shop);

			TiktokUserProxy tiktokUserProxy = new TiktokUserProxy();
			tiktokUserProxy.setProxyId(tiktokProxy.getId());
			tiktokUserProxy.setUserId(userId);
			userProxyMapper.insert(tiktokUserProxy);

			// 删除token用户重新登陆
			Collection<String> syskeys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + Constants.SYS_USER_KEY + "*");
			if(CollectionUtil.isNotEmpty(syskeys)){
				syskeys.forEach((key)->{
					LoginUser pcUser = redisCache.getCacheObject(key);
					if (ObjectUtil.isNotNull(pcUser) && ObjectUtil.isNotNull(pcUser.getShop())) {
						if (pcUser.getShop().getId().equals(shop.getId())) {
							redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + Constants.SYS_USER_KEY + pcUser.getToken());
						}
					}

				});
			}

			Collection<String> appkeys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + Constants.APP_USER_KEY + "*");
			if(CollectionUtil.isNotEmpty(appkeys)) {
				appkeys.forEach((key) -> {
					AppLoginUser pcUser = redisCache.getCacheObject(key);
					if (ObjectUtil.isNotNull(pcUser) && (pcUser.getShop().getId().equals(shop.getId()))) {
						redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + Constants.APP_USER_KEY + pcUser.getToken());
					}
				});
			}
		}
		return true;
	}

}
